// -*- Mode: Go; indent-tabs-mode: t -*-
//
// Copyright (C) 2018 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package main

import (
	"encoding/json"
	"fmt"
	"net/url"

	mqtt "github.com/eclipse/paho.mqtt.golang"
)

const (
	brokerUrl  = "127.0.0.1"
	brokerPort = 1883
	username   = "admin"
	password   = "public"
)

var topicSettings string = "edgex/event/mcu/settings"
var topicRealtime string = "edgex/event/mcu/realtime"
var topicSpindles string = "edgex/event/mcu/spindles"
var topicVoltages string = "edgex/event/mcu/voltages"
var topicCommand string = "edgex/event/mcu/command"

func main() {
	var mqttClientId = "Spinning-App-Test001"
	uri := &url.URL{
		Scheme: "tcp",
		Host:   fmt.Sprintf("%s:%d", brokerUrl, brokerPort),
		User:   url.UserPassword(username, password),
	}

	client, err := createMqttClient(mqttClientId, uri)
	if err != nil {
		fmt.Println(err)
	}

	defer client.Disconnect(5000)
	var qos = 0
	var topic = "edgex/event/mcu/voltages"

	token := client.Subscribe(topic, byte(qos), onDataReceivedFromDevice)
	fmt.Println("### client.Subscribe ###")
	if token.Wait() && token.Error() != nil {
		fmt.Println(token.Error())
	}

	select {}
}

func onDataReceivedFromDevice(client mqtt.Client, message mqtt.Message) {
	var request map[string]interface{}

	fmt.Printf("### onDataReceivedFromDevice begin ###\n")
	err := json.Unmarshal(message.Payload(), &request)
	if err != nil {
		fmt.Printf("Error unmarshaling payload: %s\n", err)
		return
	}

	fmt.Printf("Received Data: \n %s \n", message.Payload())
	fmt.Printf("### onDataReceivedFromDevice end ###\n")
}

func createMqttClient(clientID string, uri *url.URL) (mqtt.Client, error) {
	fmt.Printf("### Create MQTT client and connection: uri=%v clientID=%v ###\n", uri.String(), clientID)
	opts := mqtt.NewClientOptions()
	opts.AddBroker(fmt.Sprintf("%s://%s", uri.Scheme, uri.Host))
	opts.SetClientID(clientID)
	opts.SetUsername(uri.User.Username())
	password, _ := uri.User.Password()
	opts.SetPassword(password)
	opts.SetConnectionLostHandler(func(client mqtt.Client, e error) {
		fmt.Printf("Connection lost : %v", e)
		token := client.Connect()
		if token.Wait() && token.Error() != nil {
			fmt.Printf("Reconnection failed : %v", e)
		} else {
			fmt.Printf("Reconnection sucessful : %v", e)
		}
	})

	client := mqtt.NewClient(opts)
	fmt.Println("### createMqttClient ###")
	token := client.Connect()
	if token.Wait() && token.Error() != nil {
		return client, token.Error()
	}

	return client, nil
}
